package cn.tedu.csmall.product.service.impl;

import cn.tedu.csmall.product.ex.ServiceException;
import cn.tedu.csmall.product.mapper.BrandCategoryMapper;
import cn.tedu.csmall.product.mapper.BrandMapper;
import cn.tedu.csmall.product.mapper.SpuMapper;
import cn.tedu.csmall.product.pojo.dto.BrandAddNewDTO;
import cn.tedu.csmall.product.pojo.dto.BrandUpdateDTO;
import cn.tedu.csmall.product.pojo.entity.Brand;
import cn.tedu.csmall.product.pojo.vo.BrandListItemVO;
import cn.tedu.csmall.product.pojo.vo.BrandStandardVO;
import cn.tedu.csmall.product.pojo.vo.CategoryStandardVO;
import cn.tedu.csmall.product.repo.impl.BrandRedisRepositoryImpl;
import cn.tedu.csmall.product.service.IBrandService;
import cn.tedu.csmall.product.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 处理品牌数据的业务实现类
 *
 * @author Tan
 * @version 0.0.1
 */
@Slf4j
@Service
public class BrandServiceImpl implements IBrandService {
    @Autowired
    BrandMapper brandMapper;
    @Autowired
    BrandCategoryMapper brandCategoryMapper;
    @Autowired
    SpuMapper spuMapper;
    @Autowired
    BrandRedisRepositoryImpl brandRedisRepository;

    public BrandServiceImpl(){
        log.debug("创建业务对象: BrandServiceImpl");
    }

    @Override
    public void addNew(BrandAddNewDTO brandAddNewDTO) {
        log.debug("开始处理添加品牌业务,参数为:{}",brandAddNewDTO);
        //获得添加的品牌名称
        String name = brandAddNewDTO.getName();
        //判断品牌名称是否存在
        int i = brandMapper.countByName(name);
        if (i>0){
            //是: 品牌名已存在,品牌添加失败
            String message = "品牌名已存在,品牌添加失败";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        //否: 品牌名不存在,可以添加品牌
        Brand brand = new Brand();
        BeanUtils.copyProperties(brandAddNewDTO,brand);
        log.debug("准备开始插入品牌数据");
        brandMapper.insert(brand);
        log.debug("品牌数据插入完成");
    }

    @Override
    public void delete(Long id) {
        log.debug("开始处理[根据id删除品牌业务], 参数:{}",id);
        //查询品牌是否存在
        BrandStandardVO standardById = brandMapper.getStandardById(id);
        if (standardById==null) {
            //若为空,表示品牌不存在,抛出异常不能删除
            String message = "删除失败, 试图访问的数据不存在";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        //若不为空,表示品牌存在,可以进行下一步判断
        log.debug("品牌存在,可以行下一步判断");

        //判断是否存在关联的品牌数据
        log.debug("开始判断是否存在关联的品牌数据");
        int i = brandCategoryMapper.countByBrandId(id);
        if (i>0){
            //是: 存在关联数据, 不能删除,抛出异常
            String message = "存在关联的品牌数据,品牌删除失败";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //判断是否存在关联的SPU数据
        log.debug("开始判断是否存在关联的SPU数据");
        i = spuMapper.countByBrandId(id);
        if (i > 0) {
            //是: 存在关联数据, 不能删除,抛出异常
            String message = "存在关联的SPU数据,品牌删除失败";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //否: 品牌名不存在,可以删除品牌
        log.debug("不存在关联数据, 可以删除");
        brandMapper.deleteById(id);
    }

    @Override
    public void updateById(BrandUpdateDTO brandUpdateDTO) {
        log.debug("开始处理[根据id修改品牌业务], 参数:{}",brandUpdateDTO);
        //查询品牌是否存在
        BrandStandardVO standardById = brandMapper.getStandardById(brandUpdateDTO.getId());
        if (standardById == null) {
            //若为空,表示品牌不存在,抛出异常不能删除
            String message = "修改失败, 试图访问的数据不存在";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        //若不为空,表示品牌存在,可以进行下一步判断
        log.debug("id存在,可以行下一步判断");
        //是: 存在, 判断修改的名字是否有重复
        int i = brandMapper.countByName(brandUpdateDTO.getName());
        if (i > 0) {
            //是: 有重复, 抛出异常, 修改失败
            String message = "品牌名称已被占用, 修改失败";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        //否: 名称未被占用, 可以修改
        Brand brand = new Brand();
        BeanUtils.copyProperties(brandUpdateDTO, brand);
        log.debug("名称未被占用, 可以修改, 参数:{}",brand);
        i = brandMapper.update(brand);
        if (i != 1){
            String message = "修改失败, 服务器忙, 请稍后再试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }

    }

    @Override
    public List<BrandListItemVO> list() {
        log.debug("开始处理[查询品牌列表]业务");
//        List<BrandListItemVO> list = brandMapper.listBrand();
//        brandRedisRepository.saveList(list);
        return brandRedisRepository.getList();
    }

    @Override
    public void enable(Long id) {
        setEnable(id, 1);
    }

    @Override
    public void unEnable(Long id) {
        setEnable(id, 0);
    }

    @Override
    public BrandStandardVO getStandardById(Long id) {
        log.debug("开始处理查询商品分类详情业务,参数:{}",id);
        //根据id从缓存中获取数据
        BrandStandardVO brandStandardVO = brandRedisRepository.get(id);
        //判断获取到的结果是否不为null
        if (brandStandardVO != null) {
            //是: 直接返回
            log.debug("缓存中存在数据, 直接返回");
            return brandStandardVO;
        }
        //否: 从数据库中查找数据
        log.debug("缓存中不存在数据, 将从数据库中查询数据");
        brandStandardVO = brandMapper.getStandardById(id);
        //判断数据库中是否不存在数据
        if (brandStandardVO == null) {
            //是: 抛出异常, 查询失败
            String message = "品牌数据不存在,查询失败";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        //否: 将结果写入Redis缓存, 返回结果
        log.debug("准备将数据库中的数据写入Redis缓存中");
        brandRedisRepository.save(brandStandardVO);
        log.debug("将数据库中的数据写入Redis缓存中完成");
        return brandStandardVO;
    }

    @Override
    public void rebuildCache() {
        log.debug("准备删除redis缓存中的数据");
        brandRedisRepository.deleteAll();
        log.debug("删除redis缓存中的数据完成");

        log.debug("准备从数据库中读取品牌列表数据");
        List<BrandListItemVO> list = brandMapper.listBrand();
        log.debug("从数据库中读取品牌列表数据完成");

        log.debug("准备向Redis缓存中写入数据");
        brandRedisRepository.saveList(list);
        log.debug("向Redis缓存中写入数据完成");

        log.debug("准备从数据库中读取品牌详情数据");
        for (BrandListItemVO brandListItemVO : list) {
            Long id = brandListItemVO.getId();
            BrandStandardVO standardById = brandMapper.getStandardById(id);
            brandRedisRepository.save(standardById);
        }
        log.debug("向Redis缓存中写入数据完成");
    }

    private void setEnable(Long id, Integer enable){
        String[] s = {"禁用", "启用"};
        //判断id是否存在
        BrandStandardVO vo = brandMapper.getStandardById(id);
        if (vo == null) {
            //否: 不存在,抛出异常,删除失败
            String message = "品牌数据不存在,"+s[enable]+"失败";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        //是: 存在, 判断状态是否冲突
        if (vo.getEnable() == enable) {
            //是: 状态冲突, 抛出异常
            String message = "状态冲突,"+s[enable]+"失败";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        //否: 可以修改
        Brand brand = new Brand();
        brand.setId(id);
        brand.setEnable(enable);
        log.debug("准备修改, 参数:{}",brand);
        brandMapper.update(brand);
        log.debug("修改完成");
    }
}
